package test.panel3;

import test.CPU.CPUController;
import test.CPU.CPUObserver;
import test.panel4.Control;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;


public class CustomPanel extends JPanel implements CPUObserver{

    // 内存分配相关变量
    private final int diskRows = 32; // 磁盘块行数
    private final int diskCols = 32; // 磁盘块列数
    private final int memoryRows = 8; // 内存块行数
    private final int memoryCols = 8; // 内存块列数
    private final Color[] blockColors = {Color.BLUE, Color.MAGENTA, Color.GREEN}; // 已使用，未使用，交换区
    public int[][] diskBlocks; // 磁盘块
    public int[][] memoryBlocks; // 内存块

    private static volatile CustomPanel uniqueInstance;

    // 磁盘块和内存块初始化
    private CustomPanel() {
        CPUController.addObserver(this);
        diskBlocks = new int[diskRows][diskCols];
        memoryBlocks = new int[memoryRows][memoryCols];
        for (int i = 0; i < diskRows; i++){
            for (int j = 0; j < diskCols; j++) {
                diskBlocks[i][j] = 1;
                if (i >= 28) diskBlocks[i][j] = 2;
            }
        }
        for (int i = 0; i < memoryRows; i++){
            for (int j = 0; j < memoryCols; j++) {
                memoryBlocks[i][j] = 1;
            }
        }
    }

    public static CustomPanel getInstance() {
        if (uniqueInstance == null) {
            synchronized (CustomPanel.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new CustomPanel();
                }
            }
        }
        return uniqueInstance;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 600); // 设置一个默认的首选大小
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // 清空背景
        Graphics2D g2d = (Graphics2D) g; // 将 Graphics 转换为 Graphics2D

        int panelWidth = getWidth();
        int panelHeight = getHeight();

        // 计算可用绘图区域，减去文本和其他UI元素占用的空间
        //int availableHeightForBlocks = panelHeight - 150; // 假设顶部和底部有150像素的非绘图空间
        int diskBlockAreaHeight = panelHeight / 2;
        int memoryBlockAreaHeight = panelHeight / 2;

        // 计算每个块的宽度和高度，确保它们可以适配到可用空间中
        int blockWidth = Math.min((panelWidth - 40) / diskCols, (diskBlockAreaHeight - 40) / diskRows); // 减去边距
        int blockHeight = blockWidth; // 假设每个块是正方形

        /*int blockWidth = 10; // 每个块的宽度
        int blockHeight = 10; // 每个块的高度*/

        // 绘制文本
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("宋体", Font.BOLD, 20));
        g2d.drawString("磁盘块使用情况", 50, 30);

        // 遍历内存块矩阵，逐个绘制
        for (int i = 0; i < diskRows; i++) {
            for (int j = 0; j < diskCols; j++) {
                g2d.setColor(blockColors[diskBlocks[i][j]]); // 根据磁盘块状态选择颜色
                g2d.fillRect(20+j * blockWidth, i * blockHeight + 40, blockWidth - 2, blockHeight - 2); // 绘制矩形块
            }
        }

        // 绘制文本
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("宋体", Font.BOLD, 20));
        g2d.drawString("内存块使用情况", 50, diskRows * blockHeight + 80);

        for (int i = 0; i < memoryRows; i++) {
            for (int j = 0; j < memoryCols; j++) {
                g2d.setColor(blockColors[memoryBlocks[i][j]]); // 根据内存块状态选择颜色
                g2d.fillRect(20+j * blockWidth, i * blockHeight + diskRows * blockHeight + 90, blockWidth - 2, blockHeight - 2); // 绘制矩形块
            }
        }

        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("宋体", Font.BOLD, 15));
        g2d.drawString("已使用", 220, diskRows * blockHeight + 110);
        g2d.setColor(blockColors[0]);
        g2d.fillRect(270, diskRows * blockHeight + 95, 40, 20);

        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("宋体", Font.BOLD, 15));
        g2d.drawString("未使用", 220, diskRows * blockHeight + 140);
        g2d.setColor(blockColors[1]);
        g2d.fillRect(270, diskRows * blockHeight + 125, 40, 20);

        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("宋体", Font.BOLD, 15));
        g2d.drawString("交换区", 220, diskRows * blockHeight + 170);
        g2d.setColor(blockColors[2]);
        g2d.fillRect(270, diskRows * blockHeight + 155, 40, 20);

        // 强制抗锯齿，提高图形质量
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }

    // 根据起始位置和终止位置，设置磁盘块颜色
    public void setDiskBlocks(int startRows, int startCols, int endRows, int endCols, Color color) {
        if(startRows == endRows) {
            for (int i = startCols; i <= endCols; i++){
                diskBlocks[startRows][i] = color.equals(blockColors[0]) ? 0 : color.equals(blockColors[1]) ? 1 : 2;
            }
        } else {
            for (int i = startCols; i < diskCols; i++) {
                diskBlocks[startRows][i] = color.equals(blockColors[0]) ? 0 : color.equals(blockColors[1]) ? 1 : 2;
            }
            for (int i = startRows + 1; i <= endRows - 1; i++) {
                for (int j = 0; j < diskCols; j++) {
                    diskBlocks[i][j] = color.equals(blockColors[0]) ? 0 : color.equals(blockColors[1]) ? 1 : 2;
                }
            }
            for (int i = 0; i <= endCols; i++) {
                diskBlocks[endRows][i] = color.equals(blockColors[0]) ? 0 : color.equals(blockColors[1]) ? 1 : 2;
            }
        }
    }

    // 根据起始位置和终止位置，设置内存块颜色
    public void setMemoryBlocks(int startRows, int startCols, int endRows, int endCols, Color color) {
        if(startRows == endRows) {
            for (int i = startCols; i <= endCols; i++){
                memoryBlocks[startRows][i] = color.equals(blockColors[0]) ? 0 : color.equals(blockColors[1]) ? 1 : 2;
            }
        } else {
            for (int i = startCols; i < memoryCols; i++) {
                memoryBlocks[startRows][i] = color.equals(blockColors[0]) ? 0 : color.equals(blockColors[1]) ? 1 : 2;
            }
            for (int i = startRows + 1; i <= endRows - 1; i++) {
                for (int j = 0; j < memoryCols; j++) {
                    memoryBlocks[i][j] = color.equals(blockColors[0]) ? 0 : color.equals(blockColors[1]) ? 1 : 2;
                }
            }
            for (int i = 0; i <= endCols; i++) {
                memoryBlocks[endRows][i] = color.equals(blockColors[0]) ? 0 : color.equals(blockColors[1]) ? 1 : 2;
            }
        }
    }

    @Override
    public void CPUUpdate(int clock) {
        repaint();
    }
}
